import { forwardRef, PropsWithChildren, ReactElement } from 'react'
import _ from 'lodash'
import classnames from 'classnames'
import { GetProps, Table, TableProps } from 'antd'
import type { AnyObject } from 'antd/es/_util/type'

import styles from './styles.module.less'

type TCusTable = <T extends AnyObject = AnyObject>(
  props: PropsWithChildren<ICusTableProps<T>> & Pick<GetProps<typeof Table>, 'ref' | 'key'>,
) => ReactElement

/** CusTable 组件 Props */
export interface ICusTableProps<T = any> extends TableProps<T> {
  /** 在垂直方向上使用 flex 布局 --- scroll.x、scroll.y、sticky、tableLayout 将被忽略 */
  verticalFlexLayout?: boolean
}

/** CusTable 组件实例 --- 当使用 verticalFlexLayout 布局时，scrollTo 方法传入 top 是无效的，应该传入 index 或 key */
export type TCusTableIns = NonNullable<
  Parameters<Extract<NonNullable<Parameters<TCusTable>[0]['ref']>, (...args: any[]) => any>>[0]
>

/** antd Table 组件封装 */
export const CusTable = Object.assign(
  forwardRef(function CusTableForwardRefRender(
    props: Omit<Parameters<TCusTable>[0], 'ref'>,
    ref: Parameters<TCusTable>[0]['ref'],
  ) {
    const { verticalFlexLayout, ...antdProps } = props
    const { className, scroll, sticky, tableLayout } = antdProps

    return (
      <Table
        {...antdProps}
        className={classnames(className, !!verticalFlexLayout && styles.verticalFlexLayout)}
        scroll={verticalFlexLayout ? { x: true, scrollToFirstRowOnChange: !!scroll?.scrollToFirstRowOnChange } : scroll}
        sticky={verticalFlexLayout ? false : sticky}
        tableLayout={verticalFlexLayout ? 'fixed' : tableLayout}
        ref={ref}
      />
    )
  }) as TCusTable,

  {
    scrollToTop: (tableIns: TCusTableIns | null, top = 0) => {
      if (!tableIns) return
      if (tableIns.nativeElement.classList.contains(styles.verticalFlexLayout)) {
        const scrollBox = tableIns.nativeElement.querySelector('.ant-table-content')
        if (scrollBox) {
          scrollBox?.scrollTo({ top, behavior: 'smooth' })
          return
        }
      }
      tableIns.scrollTo({ top })
    },
    displayName: 'CusTable',
    ..._.pick(Table, [
      'SELECTION_COLUMN',
      'EXPAND_COLUMN',
      'SELECTION_ALL',
      'SELECTION_INVERT',
      'SELECTION_NONE',
      'Column',
      'ColumnGroup',
      'Summary',
    ]),
  },
)
